home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dicehelp / fails.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  26KB  |  1,022 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6. /*
  7. **    $Id: fails.c,v 30.0 1994/06/10 18:05:49 dice Exp $
  8. **
  9. **    Dice help system.  Searches an index file for a given
  10. **    keyword.  Returns either filename information, or the actual
  11. **    clip to the console, clipboard, or Rexx RESULT.
  12. **
  13. */
  14. /*
  15. **
  16. **    BUGS
  17. **              Z mode has no way to return the search key.
  18. **
  19. **        REXXSTARTUP exit if already resident.  (No, kill old).
  20. **              Currently gets enforcer hit!
  21. **
  22. **        Looses $30 (48) bytes of memory when started from Workbench.
  23. **
  24. **        CLI/WB invocation should use resident index file
  25. **
  26. **              If memory is less than XX bytes free, flush self on exit.
  27. **
  28. **        DICEHelp from Workbench accounts for "reasonable" font
  29. **        sizes.    Very large font sizes, however, blow it up.
  30. **
  31. **    !!!TODO
  32. **        If cursor is on "console.doc" in
  33. **              "work:doc/doc/console.doc/OpenDevice",
  34. **        return the console doc in full.
  35. **
  36. **        (Return # of lines for open window? Useful for small clips).
  37. **
  38. **        Make search faster -- check case insensitive first.
  39. **        (Actually this is obsolete -- new tokenized index file
  40. **        is needed to deal with automatic multiple references).
  41. **
  42. **        Match plural mismatch with error index of -3? (See error
  43. **        weighting system).
  44. **
  45. **              Show return error message as text.
  46. **
  47. **              Workbench won't read full files directly.
  48. **
  49. **    Add to Manual:
  50. **        Errors to manual. CLIP. STDOUT. QUITTING.
  51. **        Spaces are ok.    Upper case.  Q <dummy>
  52. **        Nuke 'R'.  Break old DICEHelp.
  53. **              If memory is less than XX bytes free, flush self on exit.
  54. **
  55. **
  56. **    New HELP Items:
  57. **        Put Carolyn's 68000 cards on line.  She says this is OK,
  58. **                      with credit.
  59. **
  60. **        Help on error messages.
  61. **
  62. **        Help on C keywords
  63. **
  64. */
  65. #define D(x)    ;
  66. #define    X(x)    ;
  67. #undef CLIPSUPPORT      /* Enable/disable clipboard.device code.
  68.         Clipboard support is slightly broken right now, but could be fixed */
  69.  
  70. #include <clib/exec_protos.h>
  71. #include <clib/alib_protos.h>
  72. #include <rexx/rxslib.h>
  73. #include <clib/rexxsyslib_protos.h>
  74. #include <dos/dos.h>
  75. #include <exec/memory.h>
  76. #ifdef  CLIPSUPPORT
  77. #include <devices/clipboard.h>
  78. #endif
  79. #include <DICEHelp_rev.h>
  80.  
  81. #include <strings.h>
  82. #include <stdio.h>
  83. #include <ctype.h>
  84.  
  85.  
  86. /*******************************************************************************
  87. **    Errors.
  88. */
  89. #define OK_TEMPFILE      1      // Tempfile has been created
  90. #define OK_FULLFILE      2      // Full path name has been returned
  91. #define ERROR_NOTOOLTYPE 3    // No VIEWER tooltype
  92. #define ERROR_NOTFOUND     4    // Can't find search string
  93. #define ERROR_BADFORMAT  5    // Badly formatted line in index file
  94. #define ERROR_BADCOMMAND 6    // Unrecognised AREXX command
  95. #define ERROR_READFILE     7    // Error reading help file
  96. #define ERROR_NOMEMORY     8    // Out of memory error
  97. #define ERROR_WRITEFILE  9    // Error writing temporary file to T:    !!!
  98. #define ERROR_NOCLIP     10    // Can't open clipboard.device          !!!
  99. #define ERROR_NOCLIPSUP     11    // Don't even support clipboard
  100. #define ERROR_INTERNAL     12    // Ohh, baby!
  101. #define    ERROR_MAXERRNO     12    // Distinguish error from pointer
  102.  
  103. struct ExtRexxMsgPort {
  104.    struct MsgPort  rmp_Port;
  105.    struct MinList  rmp_SearchNodes;
  106. };
  107.  
  108. struct SearchNode {
  109.     struct MinNode    sn_Node;    // Linkage
  110.     char *        sn_FileName;    // Full path to load file from
  111.     char *        sn_FileData;    // Loaded file, or NULL if unloaded
  112.     unsigned long    sn_FileSize;    // Length of file, if known
  113. };
  114.  
  115. #define unless(x)    if(!(x))
  116. #define until(x)    while(!(x))
  117.  
  118. /*******************************************************************************
  119. **    Prototypes
  120. */
  121. void    *rexxOpen(void);
  122. void     rexxClose(void);
  123. void     rexxReply(struct RexxMsg *msg,int Result1,int Result2,char *string);
  124.  
  125. void    *clipOpen(void);
  126. void     clipClose(void);
  127. LONG     clipWrite(char *string);
  128. LONG     clipLongWrite(LONG *ldata);
  129. int     getHelp(int outmode, char *searchline, int curpos);
  130.  
  131. char    *searchOpen(void);
  132. void     searchClose(void);
  133. char    *searchMe(char *strings,char *searchfor,char **filename);
  134. void     convertFile(char *file,ULONG length);
  135.  
  136. void     debugPrintSN(void);
  137.  
  138. void     startOutput( char outmode );
  139. void     sendOutput( char outmode, char *outstring, ULONG outlength );
  140. char    *endOutput( char outmode );
  141.  
  142. char    *StringScan( char *instring );
  143. char    *tailpath_p( char *searchline );
  144. int     isCollectable(char c);
  145. char    *ErrorText( int error, void * auxdata );
  146.  
  147. /*******************************************************************************
  148. **    Globals
  149. */
  150. struct RsxLib        *RexxSysBase    =0;    // Rexxsyslib.library base
  151. struct MsgPort        *rexxPort    =0;    // Our Rexx port
  152.  
  153. struct IOClipReq    *clipIO    =0;        // Clipboard Access
  154. struct List         SearchNodes;        // List of struct SearchNode
  155.  
  156. char             rexxName[]="DICEHELP";    // !! No string optimization
  157. #define                 PORT_PRI        5       // Slighly above the rabble
  158. const char  IdString[] = { VERSTAG };
  159.  
  160. #define OUTMODE_CLIP        'C'
  161. #define OUTMODE_STDOUT        'S'
  162. #define OUTMODE_FILE        'T'
  163. #define    OUTMODE_CRUTCHES    'Z'
  164.  
  165. #define COMMAND_QUIT        'Q'
  166.  
  167.  
  168. #define TEMPFILE_NAME        "t:DICEHelp.temp"       // hard coded, too
  169. #define    TEMPFILE_LEN        15    // DICE has no strlen() optimization
  170.  
  171.  
  172. disable_break()
  173. {
  174.     return(0);
  175. }
  176.  
  177. /*******************************************************************************
  178. **
  179. **    Workbench support
  180. */
  181. #include "intuition/intuition.h"
  182. #include <clib/intuition_protos.h>
  183. #include <clib/icon_protos.h>
  184. #include <workbench/workbench.h>
  185. #include <workbench/startup.h>
  186.  
  187. #define STRING_MAX 90                // !! Fixed size
  188. char    buf_string[STRING_MAX];         // !! Fixed size
  189. char    commandline[STRING_MAX];        // !! Fixed size
  190.  
  191. #define GX    10
  192. #define GY    25
  193. #define GWIDTH    400
  194. #define GHEIGHT 30
  195.  
  196. struct StringInfo si =
  197. {
  198. buf_string,    // String
  199. NULL,        // Undo
  200. 0,        // Buffer position
  201. STRING_MAX,    // Count
  202. 0,        // Disp Pos
  203. 0,        // Undo pos
  204. 0,        // Num    Chars
  205. 0,        // DispCount
  206. 0,0,        // CLeft,CTop
  207. NULL,        // Layer
  208. 0,        // LongInt
  209. NULL        // Alternate keymap
  210. };
  211.  
  212. struct Gadget gt =
  213. {
  214. NULL,
  215. GX,GY,
  216. GWIDTH,GHEIGHT,
  217. GADGHBOX,
  218. RELVERIFY,
  219. STRGADGET,
  220. NULL,
  221. NULL,
  222. NULL,
  223. 0,
  224. &si,
  225. 0,
  226. NULL
  227. };
  228.  
  229. struct NewWindow nw =
  230. {
  231. ((640-GWIDTH+20)/2),75,     /* Left, Top */
  232. GWIDTH+20,GHEIGHT+20,
  233. -1,-1,
  234. IDCMP_CLOSEWINDOW|IDCMP_GADGETUP,
  235. WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|
  236. WFLG_SMART_REFRESH|WFLG_ACTIVATE,
  237. >,
  238. NULL,
  239. "DICEHelp: Please enter a word:",
  240. NULL,NULL,
  241. 0,0,
  242. 0,0,
  243. WBENCHSCREEN,
  244. };
  245.  
  246.  
  247. int wbmain(struct WBStartup *wbs)
  248. {
  249. struct Window        * win;
  250. struct IntuiMessage    * msg=0;
  251. char            * filename=0;
  252. char            * temp=0;
  253.  
  254. int              rc=0;
  255.  
  256.     if ( win=OpenWindow(&nw) ) {
  257.     SetAPen(win->RPort,2);
  258.     if ((win->Height-win->BorderBottom-1) > 0) {
  259.         RectFill(win->RPort,
  260.          win->BorderLeft,
  261.          win->BorderTop,
  262.          win->Width-win->BorderRight-1,
  263.          win->Height-win->BorderBottom-1,
  264.          );
  265.         }
  266.     ActivateGadget(>,win,NULL);
  267.  
  268.  
  269.     // Collect VIEWER tooltype into commandline array, else
  270.     // set RC=ERROR_NOTOOLTYPE
  271.     {
  272.     struct DiskObject    * dob;    // DICEHelp icon (for Tooltypes)
  273.     BPTR              saveLock;
  274.     saveLock = CurrentDir((BPTR)wbs->sm_ArgList[0].wa_Lock);
  275.     if (dob = GetDiskObject(wbs->sm_ArgList[0].wa_Name)) {
  276.         if (temp=FindToolType(dob->do_ToolTypes,"VIEWER") ) {
  277.         strncpy(commandline,temp,STRING_MAX-TEMPFILE_LEN-2);
  278.         strncat(commandline," ",STRING_MAX);
  279.         strncat(commandline,TEMPFILE_NAME,STRING_MAX);
  280.         } else {
  281.         SetWindowTitles(win,"No \"VIEWER\" ToolType in icon!",(void *)-1);
  282.         rc= ERROR_NOTOOLTYPE;
  283.         // Window stays open for message, but user can't do anything.
  284.         }
  285.         FreeDiskObject(dob);
  286.     }
  287.     CurrentDir(saveLock);
  288.     }
  289.  
  290.  
  291.     unless( searchOpen() ) {
  292.         SetWindowTitles(win,"Can't open file \"s:DICEHelp.index\"!",(void *)-1);
  293.         rc= ERROR_READFILE;
  294.         // Window stays open for message, but user can't do anything.
  295.         }
  296.  
  297.     // Loop until we process a message (Any message causes us to exit
  298.     int looping=1;
  299.     while(looping && Wait(1L << win->UserPort->mp_SigBit))
  300.     {
  301.         while(msg = (struct IntuiMessage *) GetMsg(win->UserPort) )
  302.         {
  303.         switch( msg->Class )
  304.         {
  305.             case CLOSEWINDOW:
  306.             looping=0;
  307.             break;
  308.             case GADGETUP:
  309.             if (!rc) {
  310.                 SetWindowTitles(win, commandline,(void *)-1);
  311.                 if (looping=getHelp( OUTMODE_FILE, buf_string, 0 )) {
  312.                 DisplayBeep(0L);
  313.                 if (looping==ERROR_NOTFOUND) {
  314.                     SetWindowTitles(win,"Word not found!",(void *)-1);
  315.                 } else {
  316.                     SetWindowTitles(win,"Error reading file!",(void *)-1);    // !!! What file?
  317.                 }
  318.                 looping=1;    // Stay, show message
  319.                 ActivateGadget(>,win,NULL);    // Re-juice gadget
  320.                 } else {
  321.                 //
  322.                 // !!!! :TODO:
  323.                 // Under 2.0: fh=Open("CON:0/0/200/200/DICEHelp Error/AUTO/CLOSE/WAIT",MODE_NEWFILE);
  324.                 // Under 1.3: fh=Open("NIL:",MODE_NEWFILE);
  325.                 //
  326.                 // Note: Execute does not return a sane code under 2.0!
  327.                 //
  328.                 if( Execute(commandline,NULL,Open("NIL:",MODE_NEWFILE)) )
  329.                     looping=0;
  330.                 else
  331.                     DisplayBeep(0L);
  332.                 }
  333.             }
  334.             break;
  335.             default:
  336.         }
  337.         ReplyMsg( msg );
  338.         }
  339.     }
  340.     if (win)    CloseWindow(win);
  341.     searchClose();
  342.  
  343.     }    // OpenWindow
  344. }
  345.  
  346.  
  347. /*******************************************************************************
  348. **    CLI Startup
  349. */
  350. main(int argc,char * argv[])
  351. {
  352. struct RexxMsg *msg;
  353.  
  354. char    *filename=0;
  355. char    *refline =0;
  356.  
  357. char    *temp=0;
  358. char     outmode=0;
  359. char    *rexxresult=0;
  360. int     returncode=0;
  361.  
  362.     onbreak( disable_break );
  363.  
  364.     if (argc != 2 || ( argc == 2  &&  *argv[1]=='?' ) ) {
  365.     printf("DICEhelp <Searchstring> [REXXSTARTUP]\n");
  366.     printf("; Return help for searchstring.  See MakeIndex & s:DICEHelp.index\n");
  367.     exit(5);
  368.     }
  369.  
  370.     unless( searchOpen() ) {
  371.         puts( ErrorText( ERROR_READFILE, "s:DICEHelp.index" ));
  372.     exit(10);       // !!! Modify to return REXX result
  373.     }
  374.  
  375.     if( strcmp(argv[1],"REXXSTARTUP") )
  376.     {
  377.             temp=getHelp( OUTMODE_STDOUT, argv[1], 0 );
  378.                 unless( temp[0] == 'S')
  379.                         puts( temp+2 ); // Error
  380.     }
  381.     else{    // REXXSTARTUP
  382.     unless( rexxOpen() ) {    // !!! Error check
  383.         printf("Error: Can't open \"rexxsyslib.library\"\n");
  384.         }
  385.         #ifdef  CLIPSUPPORT
  386.     unless( clipOpen() ) {
  387.         printf("Error: Can't open \"clipboard.device\"\n");
  388.         }
  389.         #endif
  390.  
  391.     D(printf("REXX port open for traffic!\n"));
  392.  
  393.     until( outmode == 'Q' || SIGBREAKF_CTRL_C &
  394.            Wait(1L << rexxPort->mp_SigBit | SIGBREAKF_CTRL_C) ) {
  395.         while( msg=GetMsg((struct MsgPort *)rexxPort) ) {
  396.  
  397.         temp = msg->rm_Args[0];
  398.         D(printf("Message %lx, rm_Args[0] @ %lx:\n%s\n",msg,temp,temp));
  399.  
  400.         rexxresult=0;
  401.         returncode = ERROR_BADCOMMAND;
  402.         if( (3 < strlen(temp)) && (temp[1]==' ') )
  403.             {
  404.             outmode = temp[0];
  405.             printf("Outmode = %c\n", outmode);
  406.             if ( outmode == 'Q' )
  407.             rexxresult = "QUITTING";
  408.             else if ( outmode == 'Z' )
  409.             rexxresult = getHelp( OUTMODE_FILE, &temp[2], -1 );
  410.             else
  411.             rexxresult = getHelp( OUTMODE_FILE, &temp[2], 0 );
  412.             }
  413.         if( rexxresult )
  414.             returncode = 0;
  415.         rexxReply( msg,returncode,0,rexxresult );
  416.         }  // While messages
  417.         }       // Until exit
  418.         #ifdef  CLIPSUPPORT
  419.     clipClose();
  420.         #endif
  421.     rexxClose();
  422.     }
  423.  
  424.     D(printf("Exiting...\n"));
  425.     searchClose();
  426.     return(returncode);
  427. }
  428.  
  429. #ifdef    NOTDEF
  430. /*******************************************************************************
  431. **    Debug functions
  432. */
  433. void debugPrintSN(void)
  434. {
  435. struct SearchNode *nd=(struct SearchNode *)&SearchNodes;
  436.  
  437.     while((nd=nd->sn_Node.mln_Succ) && (nd->sn_Node.mln_Succ)) {
  438.         printf("SearchNode at %lx\n",nd);
  439.         printf("sn_FileName     =%s\n",nd->sn_FileName);
  440.         printf("sn_FileSize     =%ld\n",nd->sn_FileSize);
  441.         printf("sn_FileData     =%lx\n\n",nd->sn_FileData);
  442.         }
  443. }
  444. #endif
  445.  
  446. /*******************************************************************************
  447. **    Index file functions
  448. */
  449. #define FILE_PAD    2    // Stick two NULLs at the end of the file
  450.  
  451. char *searchOpen(void)
  452. {
  453. struct    SearchNode *sn;
  454. ULONG    fh=0;
  455. ULONG    length;
  456. char    *body=0;
  457. char    *filename="s:DICEHelp.index";
  458.  
  459.     NewList(&SearchNodes);
  460.  
  461.     if (fh=Open(filename,MODE_OLDFILE)) {
  462.     Seek(fh,0,OFFSET_END);
  463.     if (length=Seek(fh,0,OFFSET_BEGINNING)) {
  464.         if (sn=AllocMem(sizeof(struct SearchNode),0)) {
  465.         sn->sn_FileName=filename;
  466.         sn->sn_FileData=0;
  467.         sn->sn_FileSize=length+FILE_PAD;
  468.         AddTail(&SearchNodes,sn);
  469.         if (body=AllocMem(length+FILE_PAD,0)) {
  470.             if (length==Read(fh,body,length)) {
  471.             sn->sn_FileData=body;
  472.             convertFile(body,length);    // LF->NULL & Terminate
  473.             } else {
  474.             FreeMem(body,sn->sn_FileSize);
  475.             }
  476.             }
  477.         }
  478.         }
  479.     }
  480.  
  481.     if(fh)
  482.     Close(fh);
  483.  
  484.     return(body);
  485. }
  486.  
  487. void searchClose(void)
  488. {
  489. struct SearchNode *sn;
  490. struct SearchNode *nn;
  491.  
  492.     nn=(struct SearchNode *)&SearchNodes;
  493.     nn=nn->sn_Node.mln_Succ;
  494.  
  495.     while( nn && nn->sn_Node.mln_Succ) {
  496.     sn=nn;
  497.     nn=nn->sn_Node.mln_Succ;
  498.  
  499.     D(printf("Freeing searchnode %s. %d bytes\n",sn->sn_FileName,
  500.           sn->sn_FileSize));
  501.  
  502.     if( sn->sn_FileData )
  503.         FreeMem(sn->sn_FileData,sn->sn_FileSize);
  504.     FreeMem(sn,sizeof(struct SearchNode));
  505.     }
  506. }
  507.  
  508. /*******************************************************************************
  509. **    Line parsing functions
  510. **
  511. **    Some editors have lousy "get word" functions.  Given a cursor
  512. **    position and a line, we can clip out words too.
  513. **
  514. **    ??    If the cursor is ON punctuation, return it    ??
  515. **
  516. **    The result is NULL or a pointer into the string.  The end of
  517. **    the parsed word is NULL terminated, ** MODIFYING ** the input.
  518. **
  519. **    Input lines are formatted with XX equal to the cursor position:
  520. **        Z XX Clipped line
  521. **    String is at least 4 characters long.
  522. **
  523. */
  524. int isCollectable(char c)
  525. {
  526.     if( isalnum(c) || c==':' || c=='/' || c=='_' || c=='.' || c=='\\' )
  527.         return( 1 );
  528.     return( 0 );
  529. }
  530.  
  531. char * StringScan( char *instring )
  532. {
  533. char    *tail;
  534. char    *result;
  535. unsigned long curpos;
  536. unsigned long curtemp;    //    Wordy()
  537.  
  538.     curpos = strtol( instring, &tail, 10 );
  539.     D(printf("|Input position=%ld, Line=%s\n", curpos, tail));
  540.     if ( !curpos || (*tail != ' ') )    // !!! longer than string?
  541.         return( NULL );
  542.  
  543.     curtemp    = curpos;
  544.     while( curtemp && isCollectable( tail[curtemp-1] ) )
  545.         curtemp--;
  546.     result = &tail[curtemp];
  547.     D(printf("|Start position=%ld, Tail=%s\n", curpos, result));
  548.  
  549.     curtemp = curpos;
  550.     while( isCollectable( tail[curtemp] ) )
  551.         curtemp++;    // Stops at trailing NULL, at worst
  552.     tail[curtemp]=0;
  553.     D(printf("|Final position=%ld, Result=\"%s\"\n", curtemp, result) );
  554.  
  555.     if( curtemp == curpos )    // If no characters were valid
  556.         result = 0;
  557.     return( result );
  558. }
  559.  
  560.  
  561.  
  562. /*******************************************************************************
  563. **    Output functions. Start, send and end output based on outmode.
  564. */
  565. ULONG    outfh;            // For xxxOut functions
  566.  
  567. void startOutput(char outmode)
  568. {
  569.     switch(outmode) {
  570.         case OUTMODE_CLIP:    // !!! IFF FTXT Length !!!
  571.             outfh=1;
  572.             break;
  573.         case OUTMODE_STDOUT:
  574.             outfh=1;        // Continuation flag, basically
  575.             break;
  576.         case OUTMODE_FILE:
  577.         case OUTMODE_CRUTCHES:
  578.             outfh=Open( TEMPFILE_NAME, MODE_NEWFILE );
  579.             break;
  580.         default:
  581.     }
  582. }
  583.  
  584.  
  585. void sendOutput(char outmode, char *outstring,ULONG outlength)
  586. {
  587. char *returnstring=0;
  588.  
  589.     switch(outmode) {
  590.         case OUTMODE_CLIP:
  591.                     #ifdef      CLIPSUPPORT
  592.             clipWrite(outstring);
  593.                     #endif
  594.                 break;
  595.         case OUTMODE_STDOUT:
  596.             while( outfh && outlength && (outlength=nextLine(outstring)) ) {
  597.             if( outlength != fwrite(outstring,1,outlength,stdout) )
  598.                 outlength=0;       // Terminate early
  599.             if( SIGBREAKF_CTRL_C & SetSignal( 0,SIGBREAKF_CTRL_C) ) {
  600.                 outfh = 0;
  601.                 outlength=0;
  602.                 }
  603.             outstring += outlength;
  604.             }
  605.             break;
  606.         case OUTMODE_FILE:
  607.         case OUTMODE_CRUTCHES:
  608.             if( outfh )
  609.             if( outlength != Write( outfh,outstring,outlength )) {
  610.                 Close( outfh );    // Prevent multiple "failed"
  611.                 outfh = NULL;    // requesters in case of error
  612.                 }
  613.             break;
  614.         default:
  615.     }
  616. }
  617.  
  618.  
  619. //  !! This strings should be moved to ErrorText for localization
  620. char *endOutput( char outmode )
  621. {
  622. char *returnstring="E Internal error!";
  623.  
  624.     switch(outmode) {
  625.         case OUTMODE_CLIP:
  626.             returnstring="E Clipboard not supported";
  627.             break;
  628.         case OUTMODE_STDOUT:
  629.             returnstring="S stdout";
  630.             break;
  631.         case OUTMODE_FILE:
  632.         case OUTMODE_CRUTCHES:
  633.             if( outfh )
  634.             Close( outfh );
  635.             outfh = NULL;
  636.             returnstring="T t:DICEHelp.temp";
  637.             break;
  638.         default:
  639.     }
  640.     return( returnstring );
  641. }
  642.  
  643.  
  644. /*******************************************************************************
  645. **    Arexx functions
  646. */
  647. void * rexxOpen(void)
  648. {
  649.     RexxSysBase = (struct RxsLib *)OpenLibrary("rexxsyslib.library",0L);
  650.  
  651.     if (rexxPort == NULL) {
  652.     Forbid();
  653.     if (!( rexxPort = FindPort(rexxName ) ))
  654.         rexxPort = CreatePort(rexxName, PORT_PRI);
  655.     Permit();
  656.     }
  657.  
  658.     return( RexxSysBase );
  659. }
  660.  
  661. void rexxClose(void)
  662. {
  663.     if (RexxSysBase) {
  664.     CloseLibrary(RexxSysBase);
  665.     RexxSysBase=NULL;
  666.     }
  667.  
  668.     if (rexxPort)
  669.     DeletePort(rexxPort);
  670. }
  671.  
  672. void rexxReply(struct RexxMsg *msg,int Result1,int Result2,char *string)
  673. {
  674.     msg->rm_Result1 = Result1;
  675.     msg->rm_Result2 = Result2;
  676.  
  677.     if (Result1 == 0 && (msg->rm_Action & (1L << RXFB_RESULT))) {
  678.     D(printf("Rexx Result1=%lx  Result2=%s\n",0,string));
  679.     if (string && RexxSysBase)
  680.         msg->rm_Result2 =
  681.         (LONG)CreateArgstring(string, (LONG)strlen(string)) ;
  682.     else
  683.         msg->rm_Result2 = NULL;
  684.     }
  685.     D(printf("Rexx Result1=%lx  Result2 =%lx\n",msg->rm_Result1,msg->rm_Result2));
  686.  
  687.     ReplyMsg((struct Message *)msg);
  688. }
  689.  
  690. #ifdef  CLIPSUPPORT
  691. /******************************************************************************
  692. **    Clipboard functions
  693. */
  694. void * clipOpen()
  695. {
  696. struct MsgPort *port;
  697.  
  698.     if    (port = CreatePort(0L, 0L))
  699.     {
  700.     if  (clipIO = (struct IOClipReq *)
  701.         CreateExtIO (port, sizeof (struct IOClipReq)) )
  702.         {
  703.         unless( OpenDevice ("clipboard.device", 0, clipIO, 0) )
  704.         return(clipIO);
  705.  
  706.         DeleteExtIO(clipIO);
  707.         clipIO = NULL;
  708.         }
  709.     DeletePort(port);
  710.     }
  711.  
  712.     return(0);
  713. }
  714.  
  715. void clipClose()
  716. {
  717.     if( clipIO ) {
  718.         CloseDevice(clipIO);
  719.         DeletePort(clipIO->io_Message.mn_ReplyPort);
  720.         DeleteExtIO(clipIO);
  721.         }
  722. }
  723.  
  724. LONG clipWrite(char * string)
  725. {
  726.     LONG length, slen = strlen (string);
  727.     BOOL odd = (slen & 1);    /* pad byte flag */
  728.     LONG error = 0L;
  729.  
  730.     /* Reset the clip id */
  731.     clipIO->io_ClipID = 0;
  732.  
  733.     length = (odd) ? slen + 1 : slen;
  734.     clipIO->io_Offset = 0;
  735.     error = clipLongWrite ((LONG *) "FORM");/* "FORM" */
  736.  
  737.     length += 12;
  738.     error = clipLongWrite (&length);    /* #  */
  739.     error = clipLongWrite ((LONG *) "FTXT");/* "FTXT" for example */
  740.     error = clipLongWrite ((LONG *) "CHRS");/* "CHRS" for example */
  741.     error = clipLongWrite (&slen);        /* #  (length of string) */
  742.  
  743.     clipIO->io_Command = CMD_WRITE;
  744.     clipIO->io_Error = 0;
  745.     clipIO->io_Data = (char *) string;
  746.     clipIO->io_Length = slen;        /* length of string */
  747.     error = (LONG) DoIO (clipIO);    /* text string */
  748.  
  749.     /* Write the pad byte */
  750.     if (odd)
  751.     {
  752.     clipIO->io_Command = CMD_WRITE;
  753.     clipIO->io_Error = 0;
  754.     clipIO->io_Data = NULL;
  755.     clipIO->io_Length = 1;
  756.     error = (LONG) DoIO (clipIO);
  757.     }
  758.  
  759.     /* Indicate that we're done writing to the clipboard */
  760.     clipIO->io_Command = CMD_UPDATE;
  761.     clipIO->io_Error = 0;
  762.     error = (LONG) DoIO (clipIO);
  763.  
  764.     return (error);
  765. }
  766.  
  767. LONG clipLongWrite (LONG * ldata)
  768. {
  769.     clipIO->io_Command = CMD_WRITE;
  770.     clipIO->io_Error = 0;
  771.     clipIO->io_Data = (char *) ldata;
  772.     clipIO->io_Length = 4L;
  773.     return ( (LONG) DoIO (clipIO) );
  774. }
  775. #endif
  776.  
  777. /*******************************************************************************
  778. **    Clip & Snip functions
  779. */
  780. /*
  781. **    searchline    - Search word, or raw line from editor.
  782. **    curpos        - Cursor position on line, or zero for no parsing.
  783. **    outmode        - Where to stuff it.
  784. **
  785. **    returns:
  786. **        Filename clip is stored in, or name of entire file
  787. **        Multiple references
  788. **        Name of word searched for
  789. **
  790. **    errors:
  791. **        Clip not found
  792. **        Can't open file
  793. **        Bad format
  794. */
  795. int getHelp(int outmode, char *searchline, int curpos)
  796. {
  797. struct SearchNode *sn=(struct SearchNode *)&SearchNodes; // Search
  798. int           rc=ERROR_NOTFOUND;             // Error code
  799.  
  800.         // searchline    // Passed: parameter, raw unprocessed line
  801. char    *       searchword;    // Parsed: Word to search for, ie "OpenDevice"
  802.  
  803. char          *refline;    // Searched: [searchname] [offset] [lines]
  804. char          *filename=0;    // Searched: Path name for refline
  805.  
  806. unsigned long    fh=0;
  807. unsigned long    startpos;    // Calculated from refline
  808. unsigned long    length;        // Calculated from refline
  809.  
  810. char    *    temp=0;        // Have bits, will travel.
  811. char    *    refline2;    // Multi-reference buffer
  812. char    *    filename2;    // Multi-reference buffer
  813.  
  814. char *    returnstring=0; // Indicates where to look for result.
  815.             // "CLIP"
  816.             // "STDOUT"
  817.             // "full:path"
  818.             // "t:DICEHelp.temp"
  819.  
  820.     /*
  821.     **    Parse it.  Use Z mode if a cursor position is given.
  822.     */
  823.     if( curpos ) {
  824.     searchline = StringScan( searchline );    // Modifies searchline
  825.     }
  826.  
  827.     if( searchline == NULL || strlen( searchline ) < 2 )
  828.         return( ErrorText( ERROR_NOTFOUND, "" )); 
  829.  
  830.     /*
  831.     **  Clip off "device:filename/word" to just "word"
  832.     */
  833.     searchword = tailpath_p( searchline );
  834.     D(printf("\nWord=%s, Line=%s\n",searchword, searchline ));
  835.  
  836.     /*
  837.     **  Search all lists of words.  Reject refline's that don't match
  838.     **  the expected file name.
  839.     */
  840.     refline = 0;
  841.     while( !refline && (sn=sn->sn_Node.mln_Succ) && (sn->sn_Node.mln_Succ)) {
  842.     if( sn->sn_FileData ) {
  843.         temp = sn->sn_FileData;
  844.         while( temp = searchMe(temp, searchword, &filename) ) {
  845.         D(printf("Search-Filename=%s res=%s cmp=%d\n",
  846.               filename, temp, strpathcmp( filename, searchline )));
  847.             if( !strpathcmp( filename, searchline ) ) {
  848.             refline = temp;
  849.             break;
  850.         }
  851.         temp += strlen( temp )+1;
  852.         }
  853.     }
  854.     }
  855.  
  856.     /*
  857.     **  Basic parsing of refernce line.  Checks for bad format, gets length
  858.     **  and offset.
  859.     */
  860.     unless( refline )
  861.         return( ErrorText( ERROR_NOTFOUND, searchword )); 
  862.     unless( temp=strchr(refline,0x09) )    // Search for tab
  863.         return( ErrorText( ERROR_BADFORMAT, 0 )); 
  864.     startpos=strtol(temp,&temp,16);
  865.     length=strtol(temp,&temp,16);
  866.     D(printf("Reading %s, startpos %lx, length %lx\nrefline=%s searchword=%s\n",
  867.         filename,startpos,length,refline,searchword));
  868.  
  869.     /*
  870.     **  If the index file specifies the *entire* file, and the mode is
  871.     **  tempfile, just return the full path name of the file.  This saves
  872.     **  reading the file twice, as well as memory.  Note: Multiple references
  873.     **  won't be shown; life sucks.
  874.     */
  875.     if ( outmode==OUTMODE_CRUTCHES && length==0 )
  876.         return( ErrorText( OK_FULLFILE, filename+1 )); 
  877.  
  878.     if (fh=Open(filename+1, MODE_OLDFILE)) {
  879.     Seek(fh, startpos, OFFSET_BEGINNING);
  880.     unless( length ) {        // Zero length means read *all*
  881.         Seek(fh, 0, OFFSET_END);
  882.         length=Seek(fh, 0, OFFSET_BEGINNING);
  883.         }
  884.         unless( length )
  885.             return( ErrorText( ERROR_READFILE, filename+1 ) );
  886.     if (temp=AllocMem(length+1,0)) {
  887.         if (length==Read(fh, temp, length)) {
  888.         temp[length]=0;
  889.         
  890.         startOutput( outmode );
  891.         sendOutput( outmode, temp, length );
  892.         }
  893.         FreeMem(temp,length+1);
  894.         }
  895.         else{
  896.                return( ErrorText( ERROR_NOMEMORY, length ) );
  897.             }
  898.     Close(fh);
  899.     }
  900.     else{
  901.     return( ErrorText( ERROR_READFILE, filename+1 ) );
  902.         }
  903.  
  904.     /*
  905.     **    Multiple references section.  Yes, I hacked it in.
  906.     */
  907.     sprintf(buf_string,"# %s\\%s\n", filename+1, refline);   /* First line */
  908.     sendOutput( outmode, buf_string, strlen( buf_string ) );
  909.  
  910.     refline2  = refline;
  911.     filename2 = filename;
  912.     while( refline2 )
  913.     {
  914.     X(printf("Testing for more %s entries (%s)\n",searchword,refline2));
  915.  
  916.     refline2+=strlen( refline2 )+1;
  917.     refline2 =searchMe(refline2,searchword,&temp);
  918.         if( temp )
  919.                 filename2 = temp;       // If new filename, update
  920.  
  921.     if( refline2 )
  922.                 {
  923.         X(printf("Got it: File %s refline=%lx/%s\n",
  924.         filename2,refline2,refline2));
  925.  
  926.         strcpy (buf_string, "# ");
  927.         strncat(buf_string, filename2+1,    STRING_MAX);
  928.         strncat(buf_string, "\\",        STRING_MAX);
  929.         strncat(buf_string, refline2,            STRING_MAX);
  930.         strncat(buf_string, "\n",        STRING_MAX); // !!! ANSI BUG
  931.                 sendOutput( outmode, buf_string, strlen( buf_string ) );
  932.         }
  933.     }
  934.  
  935.     return( endOutput( outmode ) );
  936. }
  937.  
  938. /*
  939. **    Reverse case insensitive string compare specialized for paths
  940. **    Compare:
  941. **        Help Request    =    foo.doc/AllocMem
  942. **        Full path    =    work:doc/foo.doc
  943. **    If path part matches full path, return 0, else return 1.    
  944. */
  945. int strpathcmp( path, candidate)
  946. const char *path;
  947. const char *candidate;
  948. {
  949. const char *pathe;
  950. const char *cande;
  951. typedef    unsigned char    ubyte;
  952.  
  953.     cande = tailpath_p( candidate );
  954.     if( cande == candidate )
  955.         return( 0 );        // Trivial case: No path to compare
  956.  
  957.     cande--;            // foo.doc/AllocMem
  958.     pathe = path+strlen(path);        //        ^
  959.  
  960.     while( (cande > candidate) && (pathe > path) ) {
  961.         pathe--;
  962.         cande--;
  963.         if (tolower(*(ubyte *)pathe) != tolower(*(ubyte *)cande))
  964.             return( 1 );
  965.         }
  966.     return( 0 );
  967. }
  968.  
  969.  
  970. /*
  971. **    Return just filename part of complete or incomplete path
  972. */
  973. char *tailpath_p( char *pathname )
  974. {
  975. char *    temp;
  976.  
  977.     if( temp=strrchr( pathname, '\\' ) )
  978.     return( ++temp );
  979.     else if( temp=strrchr( pathname, ':' ) )
  980.     return( ++temp );
  981.     else
  982.     return( pathname );
  983. }
  984.  
  985.  
  986. char *ErrorText( int error, void * auxdata )
  987. {
  988. char    * localstring;
  989.  
  990.     switch( error ) {
  991.         case OK_TEMPFILE:
  992.                 localstring = "T %s";
  993.                 break;
  994.         case OK_FULLFILE:
  995.                 localstring = "F %s";
  996.                 break;
  997.     case ERROR_NOTOOLTYPE:
  998.                 localstring = "E No \"VIEWER\" tooltype in icon!";
  999.                 break;
  1000.     case ERROR_NOTFOUND:
  1001.                 localstring = "E Item \"%s\" not found";
  1002.                 break; 
  1003.     case ERROR_BADFORMAT:
  1004.                 localstring = "E Corrupt line in s:DICEHelp.index";
  1005.                 break;
  1006.     case ERROR_BADCOMMAND:  // Handled as a rexx error number
  1007.     case ERROR_READFILE:
  1008.                 localstring = "E Error reading \"%s\"";
  1009.                 break;
  1010.     case ERROR_NOMEMORY:    // Out of memory error        !!!
  1011.                 localstring = "E Out of memory - %d bytes needed";
  1012.                 break;
  1013.     case ERROR_WRITEFILE:    // Error writing temporary file to T: !!!
  1014.                 localstring = "E Error writing \"%s\"";
  1015.         default:
  1016.                 localstring = "E Internal error!";
  1017.     }
  1018.  
  1019.     sprintf( buf_string, localstring, auxdata );  // !!! Length limit
  1020.     return( buf_string );
  1021. }
  1022.